package org.example.myleet.Utils;

import java.util.*;
import java.util.stream.Collectors;

public class Assert {
    public static void isTrue(boolean condition, String msg) {
        if (!condition) {
            throw new RuntimeException(msg);
        }
    }

    public static void isTrue(boolean condition) {
        if (!condition) {
            throw new RuntimeException("Wrong");
        }
    }

    public static <T> boolean isPass(T[] answer, T[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i] == null) {
                if (reply[i] != null) {
                    return false;
                }
            } else if (!answer[i].equals(reply[i])) {
                return false;
            }
        }
        return true;
    }

    public static boolean isObjectPass(Object answer, Object reply) {
        if (answer == reply) {
            return true;
        }
        if (answer instanceof String[]) {
            if (reply instanceof String[]) {
                return isPass((String[]) answer, (String[]) reply);
            } else if (reply instanceof List) {
                return isPass((String[]) answer, (List) reply);
            }
            return false;
        } else if (answer instanceof List) {
            if (reply instanceof String[]) {
                return isPass((String[]) answer, (String[]) reply);
            } else if (reply instanceof List) {
                return isPass((List) answer, (List) reply);
            }
            return false;
        }
        return false;
    }

    public static boolean isPass(boolean[] answer, boolean[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i] != reply[i]) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(String[] answer, List<String> reply) {
        if (answer.length != reply.size()) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (!answer[i].equals(reply.get(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(int[] answer, List<Integer> reply) {
        if (answer.length != reply.size()) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i] != reply.get(i)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(int[][] answer, List<List<Integer>> reply) {
        if (answer.length != reply.size()) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i].length != reply.get(i).size()) {
                return false;
            }
            if (answer[i][0] != reply.get(i).get(0) || answer[i][1] != reply.get(i).get(1)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(double[] answer, double[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i] != reply[i]) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(int[] answer, int[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i] != reply[i]) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(Integer[] answer, Integer[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i] != reply[i]) {
                return false;
            }
        }
        return true;
    }

    public static <T> boolean isPass(List<T> answer, List<T> reply) {
        if (answer.size() != reply.size()) {
            return false;
        }
        for (int i=0; i<answer.size(); i++) {
            if (answer.get(i) == null) {
                if (reply.get(i) != null) {
                    return false;
                }
            } else if (!answer.get(i).equals(reply.get(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(String[] answer, char[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            if (answer[i].charAt(0) != reply[i]) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(TreeNode answer, TreeNode reply) {
        if (answer == null) {
            return reply == null;
        } else {
            if (reply == null) {
                return false;
            }
            if (answer.val != reply.val) {
                return false;
            }
            if (!isPass(answer.left, reply.left)) {
                return false;
            }
            return isPass(answer.right, reply.right);
        }
    }

    public static <T> boolean isContainPass(List<T> answer, List<T> reply) {
        if (answer.size() != reply.size()) {
            return false;
        }
        for (int i=0; i<reply.size(); i++) {
            if (!answer.contains(reply.get(i))) {
                return false;
            }
        }
        return true;
    }

    public static <T> boolean isContainPass(T[] answer, List<T> reply) {
        if (answer.length != reply.size()) {
            return false;
        }
        List<T> a = Arrays.stream(answer).collect(Collectors.toList());
        for (int i=0; i<reply.size(); i++) {
            if (!a.contains(reply.get(i))) {
                return false;
            }
        }
        return true;
    }

    public static <T> boolean isContainPass(T[] answer, T[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        List<T> a = Arrays.stream(answer).collect(Collectors.toList());
        for (int i=0; i<reply.length; i++) {
            if (!a.contains(reply[i])) {
                return false;
            }
        }
        return true;
    }

    public static boolean isContainPass(int[] answer, int[] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        List<Integer> a = new ArrayList<>();
        for (int i : answer) {
            a.add(i);
        }
        for (int i=0; i<reply.length; i++) {
            if (!a.contains(reply[i])) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPassInteger(List<Integer> answer, List<Integer> reply) {
        if (answer.size() != reply.size()) {
            return false;
        }
        for (int i=0; i<answer.size(); i++) {
            if (!answer.get(i).equals(reply.get(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean isPass(int[][] answer, int[][] reply) {
        if (answer.length != reply.length) {
            return false;
        }
        if (answer[0].length != reply[0].length) {
            return false;
        }
        for (int i=0; i<answer.length; i++) {
            for (int j=0; j<answer[i].length; j++) {
                if (answer[i][j] != reply[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }

    public static boolean hasSameElement(int[] answer, List<Integer> reply) {
        Set<Integer> answerSet = new HashSet<>();
        for (int a : answer) {
            answerSet.add(a);
        }
        Set<Integer> replySet = new HashSet<>(reply);
        if (answerSet.size() != replySet.size()) {
            return false;
        }
        for (Integer a : answerSet) {
            if (!replySet.contains(a)) {
                return false;
            }
        }
        return true;
    }
}
